from django.db import models
from django.utils import timezone
from pinyin import pinyin
from django.core.exceptions import ValidationError
from django.contrib.auth import get_user_model
User = get_user_model()

import os
# 定义抽象模型（基类）
class BaseModel(models.Model):
    """所有模型的通用基类，包含创建时间、更新时间、软删除标记"""


    class Meta:
        # 关键：标记为抽象模型，不会生成数据库表
        abstract = True
        verbose_name = '物料档案'
        verbose_name_plural = '物料档案'  # 自定义复数形式，与单数相同

# Create your models here.
class StandardModel(models.Model):

    name = models.CharField(max_length=50,verbose_name='执行标准',default='')

    # 创建时间：首次保存时自动设置为当前时间，之后不会更新
    # create_at = models.DateTimeField(verbose_name='创建日期', auto_now_add=True)

    create_at = models.DateTimeField(verbose_name='创建日期',default=timezone.now ) # 默认为当前时间
    # 更新时间：每次保存（包括首次）时自动更新为当前时间
    update_at = models.DateTimeField(verbose_name='更新日期', auto_now=True)
    class Meta:
        verbose_name='执行标准'
        verbose_name_plural = '执行标准'  # 自定义复数形式，与单数相同


    def __str__(self):
        return self.name
class RawModel(models.Model):
    STATE_CHOICES = [
        ("1", "启用"),
        ("0", "停用"),
    ]

    name = models.CharField(max_length=50,verbose_name='品名',default='')
    jian_pin = models.CharField(max_length=50,verbose_name='简拼',default='', blank=True)
    quan_pin = models.CharField(max_length=50,verbose_name='全拼',default='', blank=True)
    gui_ge = models.CharField(max_length=50, verbose_name='默认规格',default='', blank=True)
    code = models.CharField(max_length=50, verbose_name='代码', default='')
    state=models.CharField(max_length=50, verbose_name='状态', default='1', choices=STATE_CHOICES)
    version = models.SmallIntegerField(verbose_name='版本',default=1)
    chan_di = models.CharField(max_length=50, verbose_name='产地', default='', blank=True)
    remark = models.CharField(max_length=255,
                              verbose_name='备注', default='', null=True, blank=True)
    TEMP_CHOICES = [
        ("1", "常温"),
        ("0", "阴凉"),
    ]
    storage_condition=models.CharField(max_length=50, verbose_name='贮存条件', default='1', choices=TEMP_CHOICES)

    # 将原来的standard字符字段改为外键关联到StandardModel
    standard = models.ForeignKey(
        StandardModel,
        on_delete=models.PROTECT,
        null=False,  # 数据库层面不允许为NULL
        blank=False,
        verbose_name='执行标准'
    )
    # 创建时间：首次保存时自动设置为当前时间，之后不会更新
    # create_at = models.DateTimeField(verbose_name='创建日期', auto_now_add=True)

    create_at = models.DateTimeField(verbose_name='创建日期',default=timezone.now ) # 默认为当前时间
    # 更新时间：每次保存（包括首次）时自动更新为当前时间
    update_at = models.DateTimeField(verbose_name='更新日期', auto_now=True)
    class Meta:
        verbose_name='原料档案'
        verbose_name_plural = '原料档案'  # 自定义复数形式，与单数相同
        # 核心修复：添加默认排序（推荐按 ID 或创建时间排序，确保顺序唯一）
        ordering = ['-id']  # 按 ID 降序（最新创建的原料排在前面）
    def save(self, *args, **kwargs):
        # 当名称存在且简拼为空时，自动生成简拼
        if self.name and not self.jian_pin:
            # 生成拼音列表（每个汉字的拼音）
            pinyin_list = pinyin.get_initial(self.name,delimiter='')  # style='first_letter' 只取首字母
            # 拼接首字母并转为大写
            self.jian_pin = pinyin_list
            print(self.jian_pin)
        # 可选：自动生成全拼
        if self.name and not self.quan_pin:
            quan_pin_list = pinyin.get(self.name,delimiter='',format='strip')
            print(quan_pin_list.lower())
            self.quan_pin = ''.join([p[0] for p in quan_pin_list]).lower()

        super().save(*args, **kwargs)
    def __str__(self):
        return self.name+'|' + ''.join([ st[1] for st in  self.STATE_CHOICES if st[0]== self.state])

class AdditiveModel(models.Model):
    '''添加剂'''
    STATE_CHOICES = [
        ("1", "启用"),
        ("0", "停用"),
    ]
    name = models.CharField(max_length=50,verbose_name='品名',default='')
    jian_pin = models.CharField(max_length=50,verbose_name='简拼',default='', blank=True)
    quan_pin = models.CharField(max_length=50,verbose_name='全拼',default='', blank=True)
    gui_ge = models.CharField(max_length=50, verbose_name='默认规格',default='', blank=True)
    code = models.CharField(max_length=50, verbose_name='代码', default='')
    state=models.CharField(max_length=50, verbose_name='状态', default='1', choices=STATE_CHOICES)
    version = models.SmallIntegerField(verbose_name='版本',default=1)
    chan_di = models.CharField(max_length=50, verbose_name='产地', default='', blank=True)
    remark = models.CharField(max_length=255,
                              verbose_name='备注', default='', null=True, blank=True)
    TEMP_CHOICES = [
        ("1", "启用"),
        ("0", "停用"),
    ]
    storage_condition = models.CharField(max_length=50, verbose_name='贮存条件', default='1', choices=TEMP_CHOICES)
    # 将原来的standard字符字段改为外键关联到StandardModel
    standard = models.ForeignKey(
        StandardModel,
        on_delete=models.PROTECT,
        null=False,  # 数据库层面不允许为NULL
        blank=False,
        verbose_name='执行标准'
    )
    # 创建时间：首次保存时自动设置为当前时间，之后不会更新
    # create_at = models.DateTimeField(verbose_name='创建日期', auto_now_add=True)

    create_at = models.DateTimeField(verbose_name='创建日期',default=timezone.now ) # 默认为当前时间
    # 更新时间：每次保存（包括首次）时自动更新为当前时间
    update_at = models.DateTimeField(verbose_name='更新日期', auto_now=True)
    class Meta:
        verbose_name='添加剂档案'
        verbose_name_plural = '添加剂档案'  # 自定义复数形式，与单数相同
        # 核心修复：添加默认排序（推荐按 ID 或创建时间排序，确保顺序唯一）
        ordering = ['-id']  # 按 ID 降序（最新创建的原料排在前面）
    def save(self, *args, **kwargs):
        # 当名称存在且简拼为空时，自动生成简拼
        if self.name and not self.jian_pin:
            # 生成拼音列表（每个汉字的拼音）
            pinyin_list = pinyin.get_initial(self.name,delimiter='')  # style='first_letter' 只取首字母
            # 拼接首字母并转为大写
            self.jian_pin = pinyin_list

        # 可选：自动生成全拼
        if self.name and not self.quan_pin:
            quan_pin_list = pinyin.get(self.name,delimiter='',format='strip')
            # print(quan_pin_list.lower())
            self.quan_pin = ''.join([p[0] for p in quan_pin_list]).lower()

        super().save(*args, **kwargs)
    def __str__(self):
        return self.name+'|' + ''.join([ st[1] for st in  self.STATE_CHOICES if st[0]== self.state])

class PackagingModel(models.Model):
    '''包材'''
    STATE_CHOICES = [
        ("1", "启用"),
        ("0", "停用"),
    ]
    name = models.CharField(max_length=50, verbose_name='品名', default='')
    jian_pin = models.CharField(max_length=50, verbose_name='简拼', default='', blank=True)
    quan_pin = models.CharField(max_length=50, verbose_name='全拼', default='', blank=True)
    gui_ge = models.CharField(max_length=50, verbose_name='默认规格', default='', blank=True)
    code = models.CharField(max_length=50, verbose_name='代码', default='')
    state = models.CharField(max_length=50, verbose_name='状态', default='1', choices=STATE_CHOICES)
    version = models.SmallIntegerField(verbose_name='版本', default=1)
    chan_di = models.CharField(max_length=50, verbose_name='产地', default='', blank=True)
    remark = models.CharField(max_length=255,
                              verbose_name='备注', default='', null=True, blank=True)
    TEMP_CHOICES = [
        ("1", "启用"),
        ("0", "停用"),
    ]
    storage_condition = models.CharField(max_length=50, verbose_name='贮存条件', default='1', choices=TEMP_CHOICES)
    # 将原来的standard字符字段改为外键关联到StandardModel
    standard = models.ForeignKey(
        StandardModel,
        on_delete=models.PROTECT,
        null=False,  # 数据库层面不允许为NULL
        blank=False,
        verbose_name='执行标准'
    )
    # 创建时间：首次保存时自动设置为当前时间，之后不会更新
    # create_at = models.DateTimeField(verbose_name='创建日期', auto_now_add=True)

    create_at = models.DateTimeField(verbose_name='创建日期', default=timezone.now)  # 默认为当前时间
    # 更新时间：每次保存（包括首次）时自动更新为当前时间
    update_at = models.DateTimeField(verbose_name='更新日期', auto_now=True)

    class Meta:
        verbose_name = '包材档案'
        verbose_name_plural = '包材档案'  # 自定义复数形式，与单数相同
        # 核心修复：添加默认排序（推荐按 ID 或创建时间排序，确保顺序唯一）
        ordering = ['-id']  # 按 ID 降序（最新创建的原料排在前面）

    def save(self, *args, **kwargs):
        # 当名称存在且简拼为空时，自动生成简拼
        if self.name and not self.jian_pin:
            # 生成拼音列表（每个汉字的拼音）
            pinyin_list = pinyin.get_initial(self.name, delimiter='')  # style='first_letter' 只取首字母
            # 拼接首字母并转为大写
            self.jian_pin = pinyin_list

        # 可选：自动生成全拼
        if self.name and not self.quan_pin:
            quan_pin_list = pinyin.get(self.name, delimiter='', format='strip')
            # print(quan_pin_list.lower())
            self.quan_pin = ''.join([p[0] for p in quan_pin_list]).lower()

        super().save(*args, **kwargs)

    def __str__(self):
        return self.name + '|' + ''.join([st[1] for st in self.STATE_CHOICES if st[0] == self.state])
class IntermediateModel(models.Model):
    '''中间品'''
    STATE_CHOICES = [
        ("1", "启用"),
        ("0", "停用"),
    ]
    name = models.CharField(max_length=50, verbose_name='品名', default='')
    jian_pin = models.CharField(max_length=50, verbose_name='简拼', default='', blank=True)
    quan_pin = models.CharField(max_length=50, verbose_name='全拼', default='', blank=True)
    gui_ge = models.CharField(max_length=50, verbose_name='默认规格', default='', blank=True)
    code = models.CharField(max_length=50, verbose_name='代码', default='')
    state = models.CharField(max_length=50, verbose_name='状态', default='1', choices=STATE_CHOICES)
    version = models.SmallIntegerField(verbose_name='版本', default=1)
    chan_di = models.CharField(max_length=50, verbose_name='产地', default='', blank=True)
    remark = models.CharField(max_length=255,
                              verbose_name='备注', default='', null=True, blank=True)
    TEMP_CHOICES = [
        ("1", "启用"),
        ("0", "停用"),
    ]
    storage_condition = models.CharField(max_length=50, verbose_name='贮存条件', default='1', choices=TEMP_CHOICES)
    # 将原来的standard字符字段改为外键关联到StandardModel
    standard = models.ForeignKey(
        StandardModel,
        on_delete=models.PROTECT,
        null=False,  # 数据库层面不允许为NULL
        blank=False,
        verbose_name='执行标准'
    )
    # 创建时间：首次保存时自动设置为当前时间，之后不会更新
    # create_at = models.DateTimeField(verbose_name='创建日期', auto_now_add=True)

    create_at = models.DateTimeField(verbose_name='创建日期', default=timezone.now)  # 默认为当前时间
    # 更新时间：每次保存（包括首次）时自动更新为当前时间
    update_at = models.DateTimeField(verbose_name='更新日期', auto_now=True)

    class Meta:
        verbose_name = '中间品档案'
        verbose_name_plural = '中间品档案'  # 自定义复数形式，与单数相同
        # 核心修复：添加默认排序（推荐按 ID 或创建时间排序，确保顺序唯一）
        ordering = ['-id']  # 按 ID 降序（最新创建的原料排在前面）

    def save(self, *args, **kwargs):
        # 当名称存在且简拼为空时，自动生成简拼
        if self.name and not self.jian_pin:
            # 生成拼音列表（每个汉字的拼音）
            pinyin_list = pinyin.get_initial(self.name, delimiter='')  # style='first_letter' 只取首字母
            # 拼接首字母并转为大写
            self.jian_pin = pinyin_list

        # 可选：自动生成全拼
        if self.name and not self.quan_pin:
            quan_pin_list = pinyin.get(self.name, delimiter='', format='strip')
            # print(quan_pin_list.lower())
            self.quan_pin = ''.join([p[0] for p in quan_pin_list]).lower()

        super().save(*args, **kwargs)

    def __str__(self):
        return self.name + '|' + ''.join([st[1] for st in self.STATE_CHOICES if st[0] == self.state])
class FinishedModel(models.Model):
    '''成品'''
    STATE_CHOICES = [
        ("1", "启用"),
        ("0", "停用"),
    ]
    name = models.CharField(max_length=50, verbose_name='品名', default='')
    jian_pin = models.CharField(max_length=50, verbose_name='简拼', default='', blank=True)
    quan_pin = models.CharField(max_length=50, verbose_name='全拼', default='', blank=True)
    gui_ge = models.CharField(max_length=50, verbose_name='默认规格', default='', blank=True)
    code = models.CharField(max_length=50, verbose_name='代码', default='')
    state = models.CharField(max_length=50, verbose_name='状态', default='1', choices=STATE_CHOICES)
    version = models.SmallIntegerField(verbose_name='版本', default=1)
    chan_di = models.CharField(max_length=50, verbose_name='产地', default='', blank=True)
    remark = models.CharField(max_length=255,
                              verbose_name='备注', default='', null=True, blank=True)
    TEMP_CHOICES = [
        ("1", "启用"),
        ("0", "停用"),
    ]
    storage_condition = models.CharField(max_length=50, verbose_name='贮存条件', default='1', choices=TEMP_CHOICES)
    # 将原来的standard字符字段改为外键关联到StandardModel
    standard = models.ForeignKey(
        StandardModel,
        on_delete=models.PROTECT,
        null=False,  # 数据库层面不允许为NULL
        blank=False,
        verbose_name='执行标准'
    )
    # 创建时间：首次保存时自动设置为当前时间，之后不会更新
    # create_at = models.DateTimeField(verbose_name='创建日期', auto_now_add=True)

    create_at = models.DateTimeField(verbose_name='创建日期', default=timezone.now)  # 默认为当前时间
    # 更新时间：每次保存（包括首次）时自动更新为当前时间
    update_at = models.DateTimeField(verbose_name='更新日期', auto_now=True)

    class Meta:
        verbose_name = '成品档案'
        verbose_name_plural = '成品档案'  # 自定义复数形式，与单数相同
        # 核心修复：添加默认排序（推荐按 ID 或创建时间排序，确保顺序唯一）
        ordering = ['-id']  # 按 ID 降序（最新创建的原料排在前面）

    def save(self, *args, **kwargs):
        # 当名称存在且简拼为空时，自动生成简拼
        if self.name and not self.jian_pin:
            # 生成拼音列表（每个汉字的拼音）
            pinyin_list = pinyin.get_initial(self.name, delimiter='')  # style='first_letter' 只取首字母
            # 拼接首字母并转为大写
            self.jian_pin = pinyin_list

        # 可选：自动生成全拼
        if self.name and not self.quan_pin:
            quan_pin_list = pinyin.get(self.name, delimiter='', format='strip')
            # print(quan_pin_list.lower())
            self.quan_pin = ''.join([p[0] for p in quan_pin_list]).lower()

        super().save(*args, **kwargs)

    def __str__(self):
        return self.name + '|' + ''.join([st[1] for st in self.STATE_CHOICES if st[0] == self.state])
class SupplierRawModel(models.Model):
    STATE_CHOICES = [
        ("1", "启用"),
        ("0", "停用"),
    ]
    name = models.CharField(max_length=50,verbose_name='供应商名',default='')
    jian_pin = models.CharField(max_length=50,verbose_name='简拼',default='', blank=True)
    quan_pin = models.CharField(max_length=50,verbose_name='全拼',default='', blank=True)
    remark = models.CharField(max_length=255, verbose_name='备注', default='', null=True, blank=True)
    state=models.CharField(max_length=50, verbose_name='状态', default='1', choices=STATE_CHOICES)
    exp_date = models.DateField(verbose_name='有效日期', default=timezone.now)
    # 多对多字段：一本书可以有多个作者
    raws = models.ManyToManyField(
        'RawModel',  # 关联的模型（可以是类名或字符串）
        related_name='suppliers',  # 反向关联名称（作者查询书籍时使用）
        verbose_name="原料"
    )
    # 创建时间：首次保存时自动设置为当前时间，之后不会更新
    # create_at = models.DateTimeField(verbose_name='创建日期', auto_now_add=True)

    create_at = models.DateTimeField(verbose_name='创建日期',default=timezone.now ) # 默认为当前时间
    # 更新时间：每次保存（包括首次）时自动更新为当前时间
    update_at = models.DateTimeField(verbose_name='更新日期', auto_now=True)
    class Meta:
        verbose_name='原料供应商'
        verbose_name_plural = '原料供应商'  # 自定义复数形式，与单数相同

    def save(self, *args, **kwargs):
        # 当名称存在且简拼为空时，自动生成简拼
        if self.name and not self.jian_pin:
            # 生成拼音列表（每个汉字的拼音）
            pinyin_list = pinyin.get_initial(self.name,delimiter='')  # style='first_letter' 只取首字母
            # 拼接首字母并转为大写
            self.jian_pin = pinyin_list
            print(self.jian_pin)
        # 可选：自动生成全拼
        if self.name and not self.quan_pin:
            quan_pin_list = pinyin.get(self.name,delimiter='',format='strip')
            print(quan_pin_list.lower())
            self.quan_pin = ''.join([p[0] for p in quan_pin_list]).lower()

        super().save(*args, **kwargs)
    def __str__(self):
        return self.name+'|' + ''.join([ st[1] for st in  self.STATE_CHOICES if st[0]== self.state])+'|<' +str(self.exp_date)
class SupplierAdditiveModel(models.Model):
    STATE_CHOICES = [
        ("1", "启用"),
        ("0", "停用"),
    ]
    name = models.CharField(max_length=50,verbose_name='供应商名',default='')
    jian_pin = models.CharField(max_length=50,verbose_name='简拼',default='', blank=True)
    quan_pin = models.CharField(max_length=50,verbose_name='全拼',default='', blank=True)

    state=models.CharField(max_length=50, verbose_name='状态', default='1', choices=STATE_CHOICES)
    remark = models.CharField(max_length=255,
                              verbose_name='备注', default='', null=True, blank=True)
    exp_date = models.DateField(verbose_name='有效日期', default=timezone.now)
    # 多对多字段：一本书可以有多个作者
    raws = models.ManyToManyField(
        'AdditiveModel',  # 关联的模型（可以是类名或字符串）
        related_name='suppliers',  # 反向关联名称（作者查询书籍时使用）
        verbose_name="添加剂"
    )
    # 创建时间：首次保存时自动设置为当前时间，之后不会更新
    # create_at = models.DateTimeField(verbose_name='创建日期', auto_now_add=True)

    create_at = models.DateTimeField(verbose_name='创建日期',default=timezone.now ) # 默认为当前时间
    # 更新时间：每次保存（包括首次）时自动更新为当前时间
    update_at = models.DateTimeField(verbose_name='更新日期', auto_now=True)
    class Meta:
        verbose_name='添加剂供应商'
        verbose_name_plural = '添加剂供应商'  # 自定义复数形式，与单数相同

    def save(self, *args, **kwargs):
        # 当名称存在且简拼为空时，自动生成简拼
        if self.name and not self.jian_pin:
            # 生成拼音列表（每个汉字的拼音）
            pinyin_list = pinyin.get_initial(self.name,delimiter='')  # style='first_letter' 只取首字母
            # 拼接首字母并转为大写
            self.jian_pin = pinyin_list

        # 可选：自动生成全拼
        if self.name and not self.quan_pin:
            quan_pin_list = pinyin.get(self.name,delimiter='',format='strip')

            self.quan_pin = ''.join([p[0] for p in quan_pin_list]).lower()

        super().save(*args, **kwargs)
    def __str__(self):
        return self.name+'|' + ''.join([ st[1] for st in  self.STATE_CHOICES if st[0]== self.state])+'|<' +str(self.exp_date)


class SupplierPackagingModel(models.Model):
    STATE_CHOICES = [
        ("1", "启用"),
        ("0", "停用"),
    ]
    name = models.CharField(max_length=50, verbose_name='供应商名', default='')
    jian_pin = models.CharField(max_length=50, verbose_name='简拼', default='', blank=True)
    quan_pin = models.CharField(max_length=50, verbose_name='全拼', default='', blank=True)

    state = models.CharField(max_length=50, verbose_name='状态', default='1', choices=STATE_CHOICES)
    remark = models.CharField(max_length=255,
                              verbose_name='备注', default='', null=True, blank=True)
    exp_date = models.DateField(verbose_name='有效日期', default=timezone.now)
    # 多对多字段：一本书可以有多个作者
    raws = models.ManyToManyField(
        'PackagingModel',  # 关联的模型（可以是类名或字符串）
        related_name='suppliers',  # 反向关联名称（作者查询书籍时使用）
        verbose_name="包材"
    )
    # 创建时间：首次保存时自动设置为当前时间，之后不会更新
    # create_at = models.DateTimeField(verbose_name='创建日期', auto_now_add=True)

    create_at = models.DateTimeField(verbose_name='创建日期', default=timezone.now)  # 默认为当前时间
    # 更新时间：每次保存（包括首次）时自动更新为当前时间
    update_at = models.DateTimeField(verbose_name='更新日期', auto_now=True)

    class Meta:
        verbose_name = '包材供应商'
        verbose_name_plural = '包材供应商'  # 自定义复数形式，与单数相同

    def save(self, *args, **kwargs):
        # 当名称存在且简拼为空时，自动生成简拼
        if self.name and not self.jian_pin:
            # 生成拼音列表（每个汉字的拼音）
            pinyin_list = pinyin.get_initial(self.name, delimiter='')  # style='first_letter' 只取首字母
            # 拼接首字母并转为大写
            self.jian_pin = pinyin_list

        # 可选：自动生成全拼
        if self.name and not self.quan_pin:
            quan_pin_list = pinyin.get(self.name, delimiter='', format='strip')

            self.quan_pin = ''.join([p[0] for p in quan_pin_list]).lower()

        super().save(*args, **kwargs)

    def __str__(self):
        return self.name + '|' + ''.join([st[1] for st in self.STATE_CHOICES if st[0] == self.state]) + '|<' + str(
            self.exp_date)
class CustomerRawModel(models.Model):
    STATE_CHOICES = [
        ("1", "启用"),
        ("0", "停用"),
    ]
    name = models.CharField(max_length=50,verbose_name='客户名',default='')
    jian_pin = models.CharField(max_length=50,verbose_name='简拼',default='', blank=True)
    quan_pin = models.CharField(max_length=50,verbose_name='全拼',default='', blank=True)

    state=models.CharField(max_length=50, verbose_name='状态', default='1', choices=STATE_CHOICES)
    exp_date = models.DateField(verbose_name='有效日期', default=timezone.now)
    remark = models.CharField(max_length=255,
                              verbose_name='备注', default='', null=True, blank=True)
    # 多对多字段：一本书可以有多个作者
    raws = models.ManyToManyField(
        'RawModel',  # 关联的模型（可以是类名或字符串）
        related_name='customers',  # 反向关联名称（作者查询书籍时使用）
        verbose_name="原料"
    )
    # 创建时间：首次保存时自动设置为当前时间，之后不会更新
    # create_at = models.DateTimeField(verbose_name='创建日期', auto_now_add=True)

    create_at = models.DateTimeField(verbose_name='创建日期',default=timezone.now ) # 默认为当前时间
    # 更新时间：每次保存（包括首次）时自动更新为当前时间
    update_at = models.DateTimeField(verbose_name='更新日期', auto_now=True)
    class Meta:
        verbose_name='原料客户'
        verbose_name_plural = '原料客户'  # 自定义复数形式，与单数相同

    def save(self, *args, **kwargs):
        # 当名称存在且简拼为空时，自动生成简拼
        if self.name and not self.jian_pin:
            # 生成拼音列表（每个汉字的拼音）
            pinyin_list = pinyin.get_initial(self.name,delimiter='')  # style='first_letter' 只取首字母
            # 拼接首字母并转为大写
            self.jian_pin = pinyin_list
            print(self.jian_pin)
        # 可选：自动生成全拼
        if self.name and not self.quan_pin:
            quan_pin_list = pinyin.get(self.name,delimiter='',format='strip')
            print(quan_pin_list.lower())
            self.quan_pin = ''.join([p[0] for p in quan_pin_list]).lower()

        super().save(*args, **kwargs)
    def __str__(self):
        return self.name+'|' + ''.join([ st[1] for st in  self.STATE_CHOICES if st[0]== self.state])+'|<' +str(self.exp_date)
class CustomerAdditiveModel(models.Model):
    STATE_CHOICES = [
        ("1", "启用"),
        ("0", "停用"),
    ]
    name = models.CharField(max_length=50,verbose_name='客户名',default='')
    jian_pin = models.CharField(max_length=50,verbose_name='简拼',default='', blank=True)
    quan_pin = models.CharField(max_length=50,verbose_name='全拼',default='', blank=True)

    state=models.CharField(max_length=50, verbose_name='状态', default='1', choices=STATE_CHOICES)
    exp_date = models.DateField(verbose_name='有效日期', default=timezone.now)
    remark = models.CharField(max_length=255,
                              verbose_name='备注', default='', null=True, blank=True)
    # 多对多字段：一本书可以有多个作者
    raws = models.ManyToManyField(
        'AdditiveModel',  # 关联的模型（可以是类名或字符串）
        related_name='customers',  # 反向关联名称（作者查询书籍时使用）
        verbose_name="原料"
    )
    # 创建时间：首次保存时自动设置为当前时间，之后不会更新
    # create_at = models.DateTimeField(verbose_name='创建日期', auto_now_add=True)

    create_at = models.DateTimeField(verbose_name='创建日期',default=timezone.now ) # 默认为当前时间
    # 更新时间：每次保存（包括首次）时自动更新为当前时间
    update_at = models.DateTimeField(verbose_name='更新日期', auto_now=True)
    class Meta:
        verbose_name='添加剂客户'
        verbose_name_plural = '添加剂客户'  # 自定义复数形式，与单数相同

    def save(self, *args, **kwargs):
        # 当名称存在且简拼为空时，自动生成简拼
        if self.name and not self.jian_pin:
            # 生成拼音列表（每个汉字的拼音）
            pinyin_list = pinyin.get_initial(self.name,delimiter='')  # style='first_letter' 只取首字母
            # 拼接首字母并转为大写
            self.jian_pin = pinyin_list

        # 可选：自动生成全拼
        if self.name and not self.quan_pin:
            quan_pin_list = pinyin.get(self.name,delimiter='',format='strip')

            self.quan_pin = ''.join([p[0] for p in quan_pin_list]).lower()

        super().save(*args, **kwargs)
    def __str__(self):
        return self.name+'|' + ''.join([ st[1] for st in  self.STATE_CHOICES if st[0]== self.state])+'|<' +str(self.exp_date)
class CustomerPackagingModel(models.Model):
    STATE_CHOICES = [
        ("1", "启用"),
        ("0", "停用"),
    ]
    name = models.CharField(max_length=50,verbose_name='客户名',default='')
    jian_pin = models.CharField(max_length=50,verbose_name='简拼',default='', blank=True)
    quan_pin = models.CharField(max_length=50,verbose_name='全拼',default='', blank=True)

    state=models.CharField(max_length=50, verbose_name='状态', default='1', choices=STATE_CHOICES)
    exp_date = models.DateField(verbose_name='有效日期', default=timezone.now)
    remark = models.CharField(max_length=255,
                              verbose_name='备注', default='', null=True, blank=True)
    # 多对多字段：一本书可以有多个作者
    raws = models.ManyToManyField(
        'PackagingModel',  # 关联的模型（可以是类名或字符串）
        related_name='customers',  # 反向关联名称（作者查询书籍时使用）
        verbose_name="包材"
    )
    # 创建时间：首次保存时自动设置为当前时间，之后不会更新
    # create_at = models.DateTimeField(verbose_name='创建日期', auto_now_add=True)

    create_at = models.DateTimeField(verbose_name='创建日期',default=timezone.now ) # 默认为当前时间
    # 更新时间：每次保存（包括首次）时自动更新为当前时间
    update_at = models.DateTimeField(verbose_name='更新日期', auto_now=True)
    class Meta:
        verbose_name='包材客户'
        verbose_name_plural = '包材客户'  # 自定义复数形式，与单数相同

    def save(self, *args, **kwargs):
        # 当名称存在且简拼为空时，自动生成简拼
        if self.name and not self.jian_pin:
            # 生成拼音列表（每个汉字的拼音）
            pinyin_list = pinyin.get_initial(self.name,delimiter='')  # style='first_letter' 只取首字母
            # 拼接首字母并转为大写
            self.jian_pin = pinyin_list

        # 可选：自动生成全拼
        if self.name and not self.quan_pin:
            quan_pin_list = pinyin.get(self.name,delimiter='',format='strip')

            self.quan_pin = ''.join([p[0] for p in quan_pin_list]).lower()

        super().save(*args, **kwargs)
    def __str__(self):
        return self.name+'|' + ''.join([ st[1] for st in  self.STATE_CHOICES if st[0]== self.state])+'|<' +str(self.exp_date)
class CustomerIntermediateModel(models.Model):
    STATE_CHOICES = [
        ("1", "启用"),
        ("0", "停用"),
    ]
    name = models.CharField(max_length=50,verbose_name='客户名',default='')
    jian_pin = models.CharField(max_length=50,verbose_name='简拼',default='', blank=True)
    quan_pin = models.CharField(max_length=50,verbose_name='全拼',default='', blank=True)

    state=models.CharField(max_length=50, verbose_name='状态', default='1', choices=STATE_CHOICES)
    exp_date = models.DateField(verbose_name='有效日期', default=timezone.now)
    remark = models.CharField(max_length=255,
                              verbose_name='备注', default='', null=True, blank=True)
    # 多对多字段：一本书可以有多个作者
    raws = models.ManyToManyField(
        'IntermediateModel',  # 关联的模型（可以是类名或字符串）
        related_name='customers',  # 反向关联名称（作者查询书籍时使用）
        verbose_name="中间品"
    )
    # 创建时间：首次保存时自动设置为当前时间，之后不会更新
    # create_at = models.DateTimeField(verbose_name='创建日期', auto_now_add=True)

    create_at = models.DateTimeField(verbose_name='创建日期',default=timezone.now ) # 默认为当前时间
    # 更新时间：每次保存（包括首次）时自动更新为当前时间
    update_at = models.DateTimeField(verbose_name='更新日期', auto_now=True)
    class Meta:
        verbose_name='中间品客户'
        verbose_name_plural = '中间品客户'  # 自定义复数形式，与单数相同

    def save(self, *args, **kwargs):
        # 当名称存在且简拼为空时，自动生成简拼
        if self.name and not self.jian_pin:
            # 生成拼音列表（每个汉字的拼音）
            pinyin_list = pinyin.get_initial(self.name,delimiter='')  # style='first_letter' 只取首字母
            # 拼接首字母并转为大写
            self.jian_pin = pinyin_list

        # 可选：自动生成全拼
        if self.name and not self.quan_pin:
            quan_pin_list = pinyin.get(self.name,delimiter='',format='strip')

            self.quan_pin = ''.join([p[0] for p in quan_pin_list]).lower()

        super().save(*args, **kwargs)
    def __str__(self):
        return self.name+'|' + ''.join([ st[1] for st in  self.STATE_CHOICES if st[0]== self.state])+'|<' +str(self.exp_date)
class CustomerFinishedModel(models.Model):

    name = models.CharField(max_length=50,verbose_name='客户名',default='')
    jian_pin = models.CharField(max_length=50,verbose_name='简拼',default='', blank=True)
    quan_pin = models.CharField(max_length=50,verbose_name='全拼',default='', blank=True)
    STATE_CHOICES = [
        ("1", "启用"),
        ("0", "停用"),
    ]
    state=models.CharField(max_length=50, verbose_name='状态', default='1', choices=STATE_CHOICES)
    exp_date = models.DateField(verbose_name='有效日期', default=timezone.now)
    remark = models.CharField(max_length=255,
                              verbose_name='备注', default='', null=True, blank=True)
    # 多对多字段：一本书可以有多个作者
    raws = models.ManyToManyField(
        'FinishedModel',  # 关联的模型（可以是类名或字符串）
        related_name='customers',  # 反向关联名称（作者查询书籍时使用）
        verbose_name="成品"
    )
    # 创建时间：首次保存时自动设置为当前时间，之后不会更新
    # create_at = models.DateTimeField(verbose_name='创建日期', auto_now_add=True)

    create_at = models.DateTimeField(verbose_name='创建日期',default=timezone.now ) # 默认为当前时间
    # 更新时间：每次保存（包括首次）时自动更新为当前时间
    update_at = models.DateTimeField(verbose_name='更新日期', auto_now=True)
    class Meta:
        verbose_name='成品客户'
        verbose_name_plural = '成品客户'  # 自定义复数形式，与单数相同

    def save(self, *args, **kwargs):
        # 当名称存在且简拼为空时，自动生成简拼
        if self.name and not self.jian_pin:
            # 生成拼音列表（每个汉字的拼音）
            pinyin_list = pinyin.get_initial(self.name,delimiter='')  # style='first_letter' 只取首字母
            # 拼接首字母并转为大写
            self.jian_pin = pinyin_list

        # 可选：自动生成全拼
        if self.name and not self.quan_pin:
            quan_pin_list = pinyin.get(self.name,delimiter='',format='strip')

            self.quan_pin = ''.join([p[0] for p in quan_pin_list]).lower()

        super().save(*args, **kwargs)
    def __str__(self):
        return self.name+'|' + ''.join([ st[1] for st in  self.STATE_CHOICES if st[0]== self.state])+'|<' +str(self.exp_date)
class UnitModel(models.Model):

    unit = models.CharField(max_length=50,verbose_name='单位',default='Kg')
    aux_unit = models.CharField(max_length=50, verbose_name='辅助单位', default='')
    unit_rel = models.DecimalField(max_digits=8, decimal_places=4,verbose_name='单位关系', default=1)
    # 创建时间：首次保存时自动设置为当前时间，之后不会更新
    # create_at = models.DateTimeField(verbose_name='创建日期', auto_now_add=True)

    create_at = models.DateTimeField(verbose_name='创建日期',default=timezone.now ) # 默认为当前时间
    # 更新时间：每次保存（包括首次）时自动更新为当前时间
    update_at = models.DateTimeField(verbose_name='更新日期', auto_now=True)
    class Meta:
        verbose_name='单位'
        verbose_name_plural = '单位'  # 自定义复数形式，与单数相同


    def __str__(self):
        return '|'.join([self.unit,self.aux_unit])
class LocationRawModel(models.Model):
    '''
    货位管理——原料
    货位：parent为空，表示没有父级，可以为库区也可以为货位
    库区允许有多个不为0的库存
    货位仅允许最多一个不为0的库存
    '''
    name = models.CharField(max_length=50,verbose_name='货位名称',default='')
    code = models.CharField(max_length=50, verbose_name='货位编码', unique=True)
    TYPE_CHOICES = [
        ("1", "库区"),
        ("0", "库位"),
    ]
    type = models.CharField(max_length=50, verbose_name='类型', default='1', choices=TYPE_CHOICES)
    remark = models.CharField(max_length=255,
                              verbose_name='备注', default='', null=True, blank=True)
    STATE_CHOICES = [
        ("1", "启用"),
        ("0", "停用"),
    ]
    state = models.CharField(max_length=50, verbose_name='状态', default='1', choices=STATE_CHOICES)
    # 将原来的standard字符字段改为外键关联到StandardModel
    parent = models.ForeignKey(
        'self',  # 使用'self'更适合自引用外键
        on_delete=models.PROTECT,
        null=True,  # 数据库层面不允许为NULL
        blank=True,
        verbose_name='父级',
    )

    create_at = models.DateTimeField(verbose_name='创建日期',default=timezone.now ) # 默认为当前时间
    # 更新时间：每次保存（包括首次）时自动更新为当前时间
    update_at = models.DateTimeField(verbose_name='更新日期', auto_now=True)
    class Meta:
        verbose_name='原料库货位'
        verbose_name_plural = '原料库货位'  # 自定义复数形式，与单数相同
    def __str__(self):
        return '|'.join([self.name,self.code])
    def clean(self):
        """模型验证方法，用于检查保存条件
        如果从货位改成库区不用验证，如果从库区改为货位就要验证该货位所有的库存仅有一个不为0的
        """
        try:

            if not self.id: #新增
                pass
            else:
                old_type=LocationRawModel.objects.filter(id=self.id).values('type').first()
                if old_type.get('type') == '1' and self.type=='0': #库区->货位
                    # 获取该货位的入库记录
                    store_details = self.store_details.filter(remaining_num__gt=0).all()
                    if store_details.count()>1:
                        raise ValidationError({"type": f"从库区调整为货位，必须保证原库区的货物剩余数》0的入库单小于2个"})

        except Exception as e:
            raise ValidationError(e)
class LocationAdditiveModel(models.Model):
    '''
    货位管理——原料
    货位：parent为空，表示没有父级，可以为库区也可以为货位
    库区允许有多个不为0的库存
    货位仅允许最多一个不为0的库存
    '''
    name = models.CharField(max_length=50,verbose_name='货位名称',default='')
    code = models.CharField(max_length=50, verbose_name='货位编码', unique=True)
    TYPE_CHOICES = [
        ("1", "库区"),
        ("0", "库位"),
    ]
    type = models.CharField(max_length=50, verbose_name='类型', default='1', choices=TYPE_CHOICES)
    remark = models.CharField(max_length=255,
                              verbose_name='备注', default='', null=True, blank=True)
    STATE_CHOICES = [
        ("1", "启用"),
        ("0", "停用"),
    ]
    state = models.CharField(max_length=50, verbose_name='状态', default='1', choices=STATE_CHOICES)
    # 将原来的standard字符字段改为外键关联到StandardModel
    parent = models.ForeignKey(
        'self',  # 使用'self'更适合自引用外键
        on_delete=models.PROTECT,
        null=True,  # 数据库层面不允许为NULL
        blank=True,
        verbose_name='父级',
    )

    create_at = models.DateTimeField(verbose_name='创建日期',default=timezone.now ) # 默认为当前时间
    # 更新时间：每次保存（包括首次）时自动更新为当前时间
    update_at = models.DateTimeField(verbose_name='更新日期', auto_now=True)
    class Meta:
        verbose_name='添加剂库货位'
        verbose_name_plural = '添加剂库货位'  # 自定义复数形式，与单数相同
    def __str__(self):
        return '|'.join([self.name,self.code])
    def clean(self):
        """模型验证方法，用于检查保存条件
        如果从货位改成库区不用验证，如果从库区改为货位就要验证该货位所有的库存仅有一个不为0的
        """
        try:

            if not self.id: #新增
                pass
            else:
                old_type=LocationAdditiveModel.objects.filter(id=self.id).values('type').first()
                if old_type.get('type') == '1' and self.type=='0': #库区->货位
                    # 获取该货位的入库记录
                    store_details = self.store_details.filter(remaining_num__gt=0).all()
                    if store_details.count()>1:
                        raise ValidationError({"type": f"从库区调整为货位，必须保证原库区的货物剩余数》0的入库单小于2个"})

        except Exception as e:
            raise ValidationError(e)
class LocationPackagingModel(models.Model):
    '''
    货位管理——原料
    货位：parent为空，表示没有父级，可以为库区也可以为货位
    库区允许有多个不为0的库存
    货位仅允许最多一个不为0的库存
    '''
    name = models.CharField(max_length=50,verbose_name='货位名称',default='')
    code = models.CharField(max_length=50, verbose_name='货位编码', unique=True)
    TYPE_CHOICES = [
        ("1", "库区"),
        ("0", "库位"),
    ]
    type = models.CharField(max_length=50, verbose_name='类型', default='1', choices=TYPE_CHOICES)
    remark = models.CharField(max_length=255,
                              verbose_name='备注', default='', null=True, blank=True)
    STATE_CHOICES = [
        ("1", "启用"),
        ("0", "停用"),
    ]
    state = models.CharField(max_length=50, verbose_name='状态', default='1', choices=STATE_CHOICES)
    # 将原来的standard字符字段改为外键关联到StandardModel
    parent = models.ForeignKey(
        'self',  # 使用'self'更适合自引用外键
        on_delete=models.PROTECT,
        null=True,  # 数据库层面不允许为NULL
        blank=True,
        verbose_name='父级',
    )

    create_at = models.DateTimeField(verbose_name='创建日期',default=timezone.now ) # 默认为当前时间
    # 更新时间：每次保存（包括首次）时自动更新为当前时间
    update_at = models.DateTimeField(verbose_name='更新日期', auto_now=True)
    class Meta:
        verbose_name='包材库货位'
        verbose_name_plural = '包材库货位'  # 自定义复数形式，与单数相同
    def __str__(self):
        return '|'.join([self.name,self.code])
    def clean(self):
        """模型验证方法，用于检查保存条件
        如果从货位改成库区不用验证，如果从库区改为货位就要验证该货位所有的库存仅有一个不为0的
        """
        try:

            if not self.id: #新增
                pass
            else:
                old_type=LocationPackagingModel.objects.filter(id=self.id).values('type').first()
                if old_type.get('type') == '1' and self.type=='0': #库区->货位
                    # 获取该货位的入库记录
                    store_details = self.store_details.filter(remaining_num__gt=0).all()
                    if store_details.count()>1:
                        raise ValidationError({"type": f"从库区调整为货位，必须保证原库区的货物剩余数》0的入库单小于2个"})

        except Exception as e:
            raise ValidationError(e)
class LocationIntermediateModel(models.Model):
    '''
    货位管理——原料
    货位：parent为空，表示没有父级，可以为库区也可以为货位
    库区允许有多个不为0的库存
    货位仅允许最多一个不为0的库存
    '''
    name = models.CharField(max_length=50,verbose_name='货位名称',default='')
    code = models.CharField(max_length=50, verbose_name='货位编码', unique=True)
    TYPE_CHOICES = [
        ("1", "库区"),
        ("0", "库位"),
    ]
    type = models.CharField(max_length=50, verbose_name='类型', default='1', choices=TYPE_CHOICES)
    remark = models.CharField(max_length=255,
                              verbose_name='备注', default='', null=True, blank=True)
    STATE_CHOICES = [
        ("1", "启用"),
        ("0", "停用"),
    ]
    state = models.CharField(max_length=50, verbose_name='状态', default='1', choices=STATE_CHOICES)
    # 将原来的standard字符字段改为外键关联到StandardModel
    parent = models.ForeignKey(
        'self',  # 使用'self'更适合自引用外键
        on_delete=models.PROTECT,
        null=True,  # 数据库层面不允许为NULL
        blank=True,
        verbose_name='父级',
    )

    create_at = models.DateTimeField(verbose_name='创建日期',default=timezone.now ) # 默认为当前时间
    # 更新时间：每次保存（包括首次）时自动更新为当前时间
    update_at = models.DateTimeField(verbose_name='更新日期', auto_now=True)
    class Meta:
        verbose_name='原料库货位'
        verbose_name_plural = '原料库货位'  # 自定义复数形式，与单数相同
    def __str__(self):
        return '|'.join([self.name,self.code])
    def clean(self):
        """模型验证方法，用于检查保存条件
        如果从货位改成库区不用验证，如果从库区改为货位就要验证该货位所有的库存仅有一个不为0的
        """
        try:

            if not self.id: #新增
                pass
            else:
                old_type=LocationIntermediateModel.objects.filter(id=self.id).values('type').first()
                if old_type.get('type') == '1' and self.type=='0': #库区->货位
                    # 获取该货位的入库记录
                    store_details = self.store_details.filter(remaining_num__gt=0).all()
                    if store_details.count()>1:
                        raise ValidationError({"type": f"从库区调整为货位，必须保证原库区的货物剩余数》0的入库单小于2个"})

        except Exception as e:
            raise ValidationError(e)
class LocationFinishedModel(models.Model):
    '''
    货位管理——原料
    货位：parent为空，表示没有父级，可以为库区也可以为货位
    库区允许有多个不为0的库存
    货位仅允许最多一个不为0的库存
    '''
    name = models.CharField(max_length=50,verbose_name='货位名称',default='')
    code = models.CharField(max_length=50, verbose_name='货位编码', unique=True)
    TYPE_CHOICES = [
        ("1", "库区"),
        ("0", "库位"),
    ]
    type = models.CharField(max_length=50, verbose_name='类型', default='1', choices=TYPE_CHOICES)
    remark = models.CharField(max_length=255,
                              verbose_name='备注', default='', null=True, blank=True)
    STATE_CHOICES = [
        ("1", "启用"),
        ("0", "停用"),
    ]
    state = models.CharField(max_length=50, verbose_name='状态', default='1', choices=STATE_CHOICES)
    # 将原来的standard字符字段改为外键关联到StandardModel
    parent = models.ForeignKey(
        'self',  # 使用'self'更适合自引用外键
        on_delete=models.PROTECT,
        null=True,  # 数据库层面不允许为NULL
        blank=True,
        verbose_name='父级',
    )

    create_at = models.DateTimeField(verbose_name='创建日期',default=timezone.now ) # 默认为当前时间
    # 更新时间：每次保存（包括首次）时自动更新为当前时间
    update_at = models.DateTimeField(verbose_name='更新日期', auto_now=True)
    class Meta:
        verbose_name='成品库货位'
        verbose_name_plural = '成品库货位'  # 自定义复数形式，与单数相同
    def __str__(self):
        return '|'.join([self.name,self.code])
    def clean(self):
        """模型验证方法，用于检查保存条件
        如果从货位改成库区不用验证，如果从库区改为货位就要验证该货位所有的库存仅有一个不为0的
        """
        try:

            if not self.id: #新增
                pass
            else:
                old_type=LocationFinishedModel.objects.filter(id=self.id).values('type').first()
                if old_type.get('type') == '1' and self.type=='0': #库区->货位
                    # 获取该货位的入库记录
                    store_details = self.store_details.filter(remaining_num__gt=0).all()
                    if store_details.count()>1:
                        raise ValidationError({"type": f"从库区调整为货位，必须保证原库区的货物剩余数》0的入库单小于2个"})

        except Exception as e:
            raise ValidationError(e)
def validate_file_size(value):
    """验证文件大小不超过5MB"""
    filesize = value.size
    if filesize > 5 * 1024 * 1024:  # 5MB
        raise ValidationError("文件大小不能超过5MB")
    allowed_extensions = ['.pdf', '.grf', '.docx']
    ext = os.path.splitext(value.name)[1].lower()
    if ext not in allowed_extensions:
        raise ValidationError('只允许上传PDF和Word.docx/grf文件')
    return value
class ReportFileModel(models.Model):
    STATE_CHOICES = [
        ("1", "启用"),
        ("0", "停用"),
    ]
    REPORT_TYPE_CHOICES = [
        ("1", "报表"),
        ("0", "子报表"),
    ]
    # 必须关联用户，才能获取request.user.id
    user = models.ForeignKey(
        User,
        on_delete=models.PROTECT,
        related_name="reports",
        verbose_name="上传用户"
    )
    code = models.CharField(max_length=50, verbose_name='报表标识', default='',null=False, blank=False,help_text='根据模型的名字来做的')
    type = models.CharField(max_length=50, verbose_name='类型', default='1', choices=REPORT_TYPE_CHOICES)
    state = models.CharField(max_length=50, verbose_name='状态', default='1', choices=STATE_CHOICES)
    default=models.BooleanField( verbose_name='默认报表',default=1)
    remarks = models.CharField(max_length=50, verbose_name='备注', default='', null=True, blank=True, )
    # 普通文件上传
    report_name = models.CharField(max_length=50, verbose_name='报表名称', null=False, blank=True)

    # 先定义动态 upload_to 函数（关键）
    def dynamic_upload_path(instance, filename):
        """
        动态生成文件上传路径
        格式: uploads/files/report/[用户ID]/[应用标签]/[模型名称]/[文件名]
        """
        # 获取模型元数据
        code = instance.code  # 应用标签


        # 获取用户ID（确保模型有user字段关联）
        user_id = instance.user.id
        if instance.type=='1':
            # 拼接路径（将特殊字符替换为下划线，避免路径错误）
            return f"uploads/files/report/{user_id}/{code.replace(' ', '_')}/{filename}"
        else:
            # 拼接路径（将特殊字符替换为下划线，避免路径错误）
            return f"uploads/files/report/{user_id}/{code.replace(' ', '_')}/children/{filename}"

    report_file = models.FileField(upload_to=dynamic_upload_path,validators=[validate_file_size], verbose_name='报表文件')


    create_at = models.DateTimeField(verbose_name='创建日期', default=timezone.now)  # 默认为当前时间
    # 更新时间：每次保存（包括首次）时自动更新为当前时间
    update_at = models.DateTimeField(verbose_name='更新日期', auto_now=True)


    class Meta:
        verbose_name = '报表管理'
        verbose_name_plural = '报表管理'  # 自定义复数形式，与单数相同
    def __str__(self):
        return self.report_name
    def clean(self):
        """模型验证方法，用于检查保存条件"""
        print(self.report_file)
        if 'uploads/' not in self.report_file.name:
            self.report_name=self.report_file.name
        else:
            self.report_name = self.report_file.name.split('/')[-1]

